Gate or clearly label mock and fabricated data returned by API endpoints - #60
Merged
priscaenoch merged 2 commits intoAug 22, 2026
Merged
Conversation
Several endpoints returned hardcoded or synthetic data (oracle prices, cross-chain feeds, simulated bot PnL, ZK-proof "verification", price history, backfill export URLs) presented as if it were real. Add a shared src/config/mockData.ts framework that blocks these responses by default and only serves them, explicitly annotated with mock: true, when MOCK_DATA=true. The reputation leaderboard no longer needs gating at all: it now derives real per-address activity via fetchProfileData instead of a hardcoded constant chain-data stand-in. Add a CI check (check:mock-gating) that fails when a src/api file references "mock" without importing the shared framework, so new ungated fabricated-data endpoints cannot ship silently.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Several API modules returned hardcoded/fabricated data presented as real: oracle prices, cross-chain arbitrage feeds, simulated bot PnL, ZK-proof "verification", synthetic price history, and fake backfill export URLs. This PR adds a single shared framework that blocks fabricated responses by default and only serves them — always explicitly annotated
mock: true— when an operator opts in viaMOCK_DATA=true.What changed
src/config/mockData.ts:isMockDataEnabled(),annotateMock(), andsendMockGated()— the shared gating/annotation primitives. Off by default;MOCK_DATA=true(orENABLE_EXPERIMENTAL=true) opts in.src/api/oracle-feeds.ts:GET /assets/:assetPair/pricenow blocks the fabricated price by default (404) instead of always returning it.src/api/arbitrage.ts:GET /cross-chain/opportunities,GET /cross-chain/bridges, and the entire simulated-bot family (POST /bot/deploy,GET /bot/:address/status,POST /bot/:address/config,POST /bot/:address/pause) are gated — these fabricate cross-chain prices and random PnL drift.src/api/data-market.ts:GET /prices/history(synthetic sine-wave series) is gated.verifyZkProof()now only returnstrueinMOCK_DATAmode — outside it, a "ZK-proof" is never falsely reported as cryptographically valid (real verification isn't implemented), and the challenge/verify responses disclose this (verificationMethod, or anotewhen a zk_proof challenge is treated as failed).src/api/backfill.ts: a backfill job can no longer "complete" with a fake download URL/record count outsideMOCK_DATAmode — it fails honestly with a clearerrorMessageinstead. When it does complete (mock mode only), the response is markedmock: true.src/api/reputation.ts: the leaderboard endpoint no longer needs gating at all — it was substituting a hardcoded constant (transactionCount: 10for every profile) as the input to real score computation. It now derives real per-address activity via the existingfetchProfileData()used by every other per-address endpoint, so no fabricated data feeds into the leaderboard.src/api/sandwich.ts: cosmetic — a variable namedmockPatternsactually held real DB-derived data; renamed torecentSandwichPatternsto stop it looking like fabricated data (audit false positive).src/api/freeze.ts,src/api/predict.ts: one-line comment rewords (removed a stray "mock" mention describing real, non-fabricating code) so the new repo-wide CI guard doesn't false-positive on unrelated files.@swaggerblocks (withx-experimental: true) for the newly-gated arbitrage and data-market endpoints, and updated the oracle-feeds price doc. RegisteredOracle Feeds,Arbitrage, andData Markettags insrc/indexer/swaggerSpec.ts.scripts/check-mock-gating.ts,npm run check:mock-gating, wired into thelintjob in.github/workflows/ci.yml): fails if anysrc/apifile mentions "mock" without importing the shared framework — so a new ungated fabricated-data endpoint can't ship silently.MOCK_DATAflag, the gated-endpoint table, and the CI guard.tests/api/mock-data-gating.test.ts(blocked-by-default / labeled-when-enabled behavior for oracle-feeds, arbitrage cross-chain + bot, data-market price history; leaderboard now callsfetchProfileDataper profile instead of fabricating),tests/scripts/check-mock-gating.test.ts(guard fixture tests, including the "fails on a deliberately ungated mock file" acceptance case), plus a small update to the existingtests/archival-routes.test.tsandtests/orphaned-routers-integration.test.tsto match the new gated behavior. New test files are wired into thenpm testallowlist.Interpretation notes (ambiguous/overlapping parts of the issue)
src/api/flash-loans.ts's/mempoolendpoint is called a "stub" in the issue body, but on inspection it already returns an honest empty state (pendingHighRisk: []) with a clear explanatory message — no fabricated data is actually returned, so no code change was needed there.src/api/sandwich.ts's "mock patterns" turned out to be real DB-derived data with a misleading variable name, not fabricated data — fixed by renaming rather than gating.src/api; this required two incidental comment rewords in unrelated files (freeze.ts,predict.ts) to remove stale "mock" mentions that would otherwise false-positive the new check.Verification performed
Ran locally against this branch (Windows dev box; CI runs the same commands on
ubuntu-latest):npm run build— clean.npm run build -- --noEmit— clean (matches thelintjob's type-check step).npm run typecheck:scripts— clean.npm run lint(invoked directly aseslint "src/**/*.ts" "tests/**/*.ts" --max-warnings 400due to a local shell quoting quirk withnpm run; identical to what CI'slintjob runs) — 0 errors, 322 pre-existing warnings (well under the 400 cap; none in any file this PR touches).npm run check:mock-gating(new) — passes: no ungated mock/fabricated data insrc/api.npm run validate:prisma— passes, 431 valid field references, 0 phantom fields.npm test(the exact CI allowlist, now including the 2 new test files) — 9 test files / 200 tests passed.tests/archival-routes.test.ts(not in the CI allowlist, but touched by this PR) — 33/33 tests passed.Test plan
GET /oracle-feeds/assets/XLM-USD/price→ 404 +mock: trueby default; 200 + labeled price withMOCK_DATA=true.GET /arbitrage/cross-chain/opportunities//bridges→ gated the same way.POST /arbitrage/bot/deploy(and status/config/pause) → gated the same way.GET /data-market/prices/history→ gated the same way.fetchProfileDatais called per profile instead of a hardcoded constant.src/apitree.archival-routes.test.tscase updated to assertmock: trueon a completed request.Known pre-existing issues (not touched by this PR)
npm run validate-routesalready fails on upstreammain(10 orphaned routers —flash-loans.ts,freeze.ts,predict.ts,sandwich.ts, etc. — plus a stalePENDING_SCHEMA_ROUTERSwarning forwebhooks.ts). This script isn't wired intoci.yml; unrelated to this change.npm run audit:indexesalready reports pre-existing FK fields without indexes across many unrelated models. Not wired intoci.yml; no schema changes in this PR.tsc --noEmitover all ofsrc/**/*.ts(broader than the project's owntsconfig.jsoninclude, which only follows what's reachable fromsrc/index.ts/src/indexer/run.ts) surfaces pre-existing type errors insrc/api/reputation.tsand elsewhere, unrelated to the lines this PR touches — these files are simply outside the compiled/type-checked graph already, both before and after this change.Closes #7